import asyncio
import os
import datetime

from django import forms

from django.http import StreamingHttpResponse, JsonResponse
import cv2



from realTimeVideo.utils import vertical_apart, vertical_concat, get_result, \
    process_image, image_to_base64

os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"




def generate_video(viewMethod):
    try:
        while True:
            frame = get_result().get_frame()

            if frame is None:
                break
            if viewMethod == '上视角':
                frame = vertical_apart(frame)[0]
            elif viewMethod == '下视角':
                frame = vertical_apart(frame)[1]
            # 将帧数据转换为字节流
            ret, buffer = cv2.imencode('.jpeg', frame)
            frame_bytes = buffer.tobytes()
            # 使用 yield 将每一帧数据推送给前端

            yield (b'--frame\r\n'
                   b'Content-Type: image/jpeg\r\n\r\n' + frame_bytes + b'\r\n')
    except GeneratorExit as e:
        print(e)
        print("Client disconnected")
        # 停止继续发送数据


def video_stream(request):
    print(request)
    viewMethod = request.GET.get('viewMethod')

    try:
        # 通过 StreamingHttpResponse 将视频流作为 HTTP 响应返回给前端
        response = StreamingHttpResponse(streaming_content=generate_video(viewMethod),
                                         content_type='multipart/x-mixed-replace; boundary=frame')
        return response
    except Exception as e:
        print(e)


def verify_cert(cert, ca_cert):
    """
    :type cert: str
    :type ca_cert: str
    :rtype: bool
    """
    import OpenSSL
    try:
        cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
    except OpenSSL.crypto.Error:
        raise Exception('certificate is not correct: %s' % cert)

    try:
        ca_cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, ca_cert)
    except OpenSSL.crypto.Error:
        raise Exception('ca certificate is not correct: %s' % ca_cert)

    store = OpenSSL.crypto.X509Store()
    store.add_cert(ca_cert_obj)
    store_ctx = OpenSSL.crypto.X509StoreContext(store, cert_obj)
    try:
        store_ctx.verify_certificate()
        return True
    except OpenSSL.crypto.X509StoreContextError:
        return False


class ImageUploadForm(forms.Form):
    image = forms.ImageField()
    certificate_file = forms.FileField(label='Upload Certificate (.crt)')


def picture_upload(request):
    if request.method == 'POST':
        form = ImageUploadForm(request.POST, request.FILES)
        if form.is_valid():
            # 存储证书
            certificate_file = form.cleaned_data['certificate_file']
            with open('realTimeVideo\\digital_certificate\\server.crt', 'wb+') as destination:
                for chunk in certificate_file.chunks():
                    destination.write(chunk)
            # 校验证书
            ca_cert_name = "ca_selfsign.crt"
            server_cert_name = "server.crt"
            path = "realTimeVideo/digital_certificate/"

            ca_cert = open(path + ca_cert_name).read()
            server_cert = open(path + server_cert_name).read()
            try:
                result = verify_cert(server_cert, ca_cert)
                print("服务端证书是否由CA证书签发: %s" % result)
                if result:
                    # 处理上传的图像
                    original_image = form.cleaned_data['image']
                    # 存储图片
                    with open('realTimeVideo\\temp_image.jpg', 'wb+') as destination:
                        for chunk in original_image.chunks():
                            destination.write(chunk)
                    original_img = cv2.imread('realTimeVideo\\temp_image.jpg')

                    processed_image, label = process_image(original_img)

                    #
                    original_image = cv2.imencode('.jpeg', original_img)[1]

                    o_i = image_to_base64(original_image)
                    result_dict = {
                        "code": 200,
                        "original_image": o_i,
                        "processed_image_data": processed_image,
                        "result": label
                    }

                    return JsonResponse(result_dict)
                else:
                    print("证书校验不通过")
                    result_dict = {
                        "code": 500,
                        "error": "证书校验失败"
                    }
                    return JsonResponse(result_dict)
            except Exception as e:
                print(e)
                result_dict = {
                    "code": 500,
                    "error": "证书错误"
                }
                return JsonResponse(result_dict)
